//
// RS Game Framework
// Copyright © 2009 Jedd Haberstro
// jhaberstro@gmail.com
// 
// $Id:
//

#include "rs/unittest/TestRunner.hpp"
#include "rs/unittest/TestSuiteManager.hpp"
#include "rs/Assert.hpp"

namespace rs
{
    namespace unittest
    {            
        void TestRunner::ReportSuiteStart(TestSuite const* suite) {
            RS_ASSERT(suite != 0, "suite is null");
            for (TestReporterContainer::iterator itr = reporters_.begin(); itr != reporters_.end(); ++itr) {
                (*itr)->ReportSuiteStart(suite);
            }
        }
        
        void TestRunner::ReportSuiteEnd(TestSuite const* suite) {
            RS_ASSERT(suite != 0, "suite is null");
            for (TestReporterContainer::iterator itr = reporters_.begin(); itr != reporters_.end(); ++itr) {
                (*itr)->ReportSuiteEnd(suite);
            }
        }
        
        void TestRunner::ReportTestSuccees(TestCase const* test) {
            RS_ASSERT(test != 0, "test is null");
            for (TestReporterContainer::iterator itr = reporters_.begin(); itr != reporters_.end(); ++itr) {
                (*itr)->ReportTestSuccees(test);
            }
        }
        
        void TestRunner::ReportTestFailure(TestCase const* test, TestFailure const* failureDetails) {
            RS_ASSERT(test != 0, "test is null");
            RS_ASSERT(failureDetails != 0, "failureDetails is null");
            ++totalFailedTests_;
            for (TestReporterContainer::iterator itr = reporters_.begin(); itr != reporters_.end(); ++itr) {
                (*itr)->ReportTestFailure(test, failureDetails);
            }
        }
        
        void TestRunner::ReportSummary(unsigned int totalTests, unsigned int failedTests) {
            for (TestReporterContainer::iterator itr = reporters_.begin(); itr != reporters_.end(); ++itr) {
                (*itr)->ReportSummary(totalTests, failedTests);
            }
        }
        
        void TestRunner::AddTestReporter(TestReporter* testReporter) {
            RS_ASSERT(testReporter != 0, "testReporter is null");
            for (TestReporterContainer::iterator itr = reporters_.begin(); itr != reporters_.end(); ++itr) {
                if (*itr == testReporter) {
                    return;
                }
            }
            
            reporters_.push_back(testReporter);
        }
        
        void TestRunner::RemoveTestReporter(TestReporter* testReporter) {
            RS_ASSERT(testReporter != 0, "testReporter is null");
            for (TestReporterContainer::iterator itr = reporters_.begin(); itr != reporters_.end(); ++itr) {
                if (*itr == testReporter) {
                    reporters_.erase(itr);
                    return;
                }
            }
        }
                                
        void TestRunner::RunTests() {
            totalTests_ = 0;
            totalFailedTests_ = 0;
            
            typedef TestSuite::TestCaseContainer TestCaseContainer;
            TestSuiteManager& suiteManager = TestSuiteManager::Instance();
            for( TestSuiteManager::Iterator itr = suiteManager.Begin(); itr != suiteManager.End(); ++itr) {
                TestSuite* suite = itr->second;
                this->ReportSuiteStart(suite);
                
                for (TestCaseContainer::const_iterator caseItr = suite->GetTests().begin(); caseItr != suite->GetTests().end(); ++caseItr) {
                    ++totalTests_;
                    (*caseItr)->Run(this);
                }
                
                this->ReportSuiteEnd(suite);
            }
            
            this->ReportSummary(totalTests_, totalFailedTests_);
        }
    }
}